/* C++ 函数模板
 * 模板的意义：对类型也可以进行参数化了
 *
 * 函数模板：是不进行编译的，因为类型不知道
 * 模板的实例化：函数调用点进行实例化
 * 模板函数：才是要被编译器所编译的
 *
 * 模板类型参数：使用typename或class定义
 * 模板非类型参数：非类型参数在编译时会被直接替换为具体的值，都是常量，只能使用，不能修改
 *
 * 模板的实参推演 => 可以根据用户传入的实参类型来推导出模板类型参数的具体类型
 *
 * 模板的特例化（专用化）：
 * 特殊的实例化，不是编译器提供的，而是用户提供的
 *
 * 模板函数、模板的特例化、非模板函数（普通函数）的重载关系
 *
 * 模板代码是不能在一个文件中定义，另一个文件中使用的。
 * 模板代码在调用之前，一定要看到模板定义的地方，这样的话，模板才能够进行正常的实例话，产生能够被编译器编译的代码。
 * 所以，模板代码都是放在头文件中，然后在源文件中直接进行#include包含
 * */

#include <iostream>
#include <cstring>
using namespace std;

//函数模板
template<typename T>      //定义一个模板参数列表
bool compare(T a,T b){               //compare是一个函数模板
    cout<<"template compare"<<endl;
    return a>b;
}

/* 在函数调用点，编译器用用户指定的类型，从原模板实例化一份函数代码出来
bool compare<int>(int a,int b){               //compare是一个函数模板
    cout<<"template compare"<<endl;
    return a>b;
}

bool compare<const char*>(const char* a,const char* b){               //compare是一个函数模板
    cout<<"template compare"<<endl;
    return a>b;     //比较字符串地址无意义，因此要实现模板的特例化
}
 * */

//针对compare函数模板，提供const char*类型的特例化版本
template<>
bool compare<const char *>(const char *a,const char* b){
    cout<<"compare<const char *>"<<endl;
    return strcmp(a,b)>0;
}

//普通函数 非模板函数
bool compare(const char *a,const char* b){
    cout<<"normal compare"<<endl;
    return strcmp(a,b)>0;
}

int main(){
    //函数调用点
    compare<int>(10,20);

    //函数模板的实参推演
    compare(1.1,1.2);

    //compare(1,1.1);       //会报错

    //函数模板的实参推演  T 是  const char*
    //对于某些类型来说，依赖编译器默认实例化的模板代码，代码处理逻辑是错误的
    //编译器优先把compare处理成函数名字，没有的话才去找compare模板
    compare("aaa","bbb");
    compare<const char *>("aaa","bbb");

    return 0;
}